package es.gesfutbol.web;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import es.gesfutbol.dao.ICombinacioGeneralDao;
import es.gesfutbol.dao.ICombinacioPropiaDao;
import es.gesfutbol.dao.IEquipDao;
import es.gesfutbol.dao.IEquipEnPenyistaDao;
import es.gesfutbol.dao.IForumDao;
import es.gesfutbol.dao.IPenyaDao;
import es.gesfutbol.dao.IPenyistaDao;
import es.gesfutbol.dao.IPercentatgeDao;
import es.gesfutbol.dao.IUsuariRegistratDAO;
import es.gesfutbol.dao.IUtilsDao;
import es.gesfutbol.domini.implementacio.CombinacioGeneral;
import es.gesfutbol.domini.implementacio.CombinacioPropia;
import es.gesfutbol.domini.implementacio.Forum;
import es.gesfutbol.domini.implementacio.Penya;
import es.gesfutbol.domini.implementacio.Penyista;
import es.gesfutbol.domini.implementacio.Percentatge;
import es.gesfutbol.domini.implementacio.UsuariRegistrat;
import es.gesfutbol.web.backbean.PenyaBackBean;

public class CrearPenyaController extends MultiActionController {

	//Constants
	private String FIX1 = "generalFix1";
	private String DOBLE1 = "generalDob1";
	private String TRIPLE1 ="generalTrip1";
	private String FIX2 = "generalFix2";
	private String DOBLE2 = "generalDob2";
	private String TRIPLE2 = "generalTrip2";	
	private String FIX3 = "generalFix3";
	private String DOBLE3 = "generalDob3";
	private String TRIPLE3 = "generalTrip3";
	private String COMB_GENERAL_NOT_NUMERIC = "Las combinaciones generales deben contener valores numéricos.";
	private String TYPE_MIS_MATCH = "typemismatch";
	private String PERCENTATGE_NOT_NUMERIC = "Los porcentajes deben contener valores numéricos";
	private String ENFRONTAMENTS_ANTERIORS = "EnfrontamentsAnteriors";
	private String CLASSIFICACIO = "Classificacio";
	private String LOCAL = "JugaComALocal";
	private String PRIMERA_VOLTA = "ResultatPartitPrimeraVolta";
	private String ULTIMS_RESULTATS = "UltimsResultatsObtinguts";
	
	private IPenyistaDao penyistaDao;

	private IUsuariRegistratDAO usuariRegistratDao;

	private MailSender mailSender;

	private SimpleMailMessage mailMessage; 

	private IEquipDao equipDao;

	private IForumDao forumDao;

	private IEquipEnPenyistaDao equipEnPenyistaDao;

	private IPenyaDao penyaDao;

	private ICombinacioGeneralDao combinacioGeneralDao;

	private ICombinacioPropiaDao combinacioPropiaDao;

	private IPercentatgeDao percentatgeDao;
	
	private IUtilsDao utilsDao;
	
	public MailSender getMailSender() {
		return mailSender;
	}

	public void setMailSender(MailSender mailSender) {
		this.mailSender = mailSender;
	}

	public SimpleMailMessage getMailMessage() {
		return mailMessage;
	}

	public void setMailMessage(SimpleMailMessage mailMessage) {
		this.mailMessage = mailMessage;
	}

	public IPenyistaDao getPenyistaDao() {
		return penyistaDao;
	}

	public void setPenyistaDao(IPenyistaDao penyistaDao) {
		this.penyistaDao = penyistaDao;
	}

	public IUsuariRegistratDAO getUsuariRegistratDao() {
		return usuariRegistratDao;
	}

	public void setUsuariRegistratDao(IUsuariRegistratDAO usuariRegistratDao) {
		this.usuariRegistratDao = usuariRegistratDao;
	}

	public IEquipDao getEquipDao() {
		return equipDao;
	}

	public void setEquipDao(IEquipDao equipDao) {
		this.equipDao = equipDao;
	}

	public IForumDao getForumDao() {
		return forumDao;
	}

	public void setForumDao(IForumDao forumDao) {
		this.forumDao = forumDao;
	}

	public IEquipEnPenyistaDao getEquipEnPenyistaDao() {
		return equipEnPenyistaDao;
	}

	public void setEquipEnPenyistaDao(IEquipEnPenyistaDao equipEnPenyistaDao) {
		this.equipEnPenyistaDao = equipEnPenyistaDao;
	}

	public IPenyaDao getPenyaDao() {
		return penyaDao;
	}

	public void setPenyaDao(IPenyaDao penyaDao) {
		this.penyaDao = penyaDao;
	}

	public ICombinacioGeneralDao getCombinacioGeneralDao() {
		return combinacioGeneralDao;
	}

	public void setCombinacioGeneralDao(ICombinacioGeneralDao combinacioGeneralDao) {
		this.combinacioGeneralDao = combinacioGeneralDao;
	}

	public ICombinacioPropiaDao getCombinacioPropiaDao() {
		return combinacioPropiaDao;
	}

	public void setCombinacioPropiaDao(ICombinacioPropiaDao combinacioPropiaDao) {
		this.combinacioPropiaDao = combinacioPropiaDao;
	}
	
	public IPercentatgeDao getPercentatgeDao() {
		return percentatgeDao;
	}

	public void setPercentatgeDao(IPercentatgeDao percentatgeDao) {
		this.percentatgeDao = percentatgeDao;
	}
	
	public IUtilsDao getUtilsDao() {
		return utilsDao;
	}

	public void setUtilsDao(IUtilsDao utilsDao) {
		this.utilsDao = utilsDao;
	}

	//	It will be just called when some validation or binding Exception occurs
	//	Otherwise, Spring will bypass it
	public ModelAndView hanldeBindException(HttpServletRequest request, HttpServletResponse response, ServletRequestBindingException bindingException) {
		BindException bindException = (BindException) bindingException.getRootCause();
		BindingResult bindingResult = (BindingResult) bindException.getModel().get(BindingResult.MODEL_KEY_PREFIX + "command");
		String error = bindingResult.getFieldError().getDefaultMessage();
		String code = bindingResult.getFieldError().getCode();
		String campo = bindingResult.getFieldError().getField();
		
		if((code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(FIX1))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(FIX1))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(DOBLE1))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(TRIPLE1))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(FIX2))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(DOBLE2))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(TRIPLE2))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(FIX3))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(DOBLE3))
				|| (code.equalsIgnoreCase(TYPE_MIS_MATCH)) && (campo.equals(TRIPLE3))){
			
			error = COMB_GENERAL_NOT_NUMERIC;
		}else if(code.equalsIgnoreCase(TYPE_MIS_MATCH)){
			error = PERCENTATGE_NOT_NUMERIC;
		}
		
		//Combinacions propies.
		List<CombinacioPropia> comb = combinacioPropiaDao.findAll();
		
        return new ModelAndView("usuari/crearPenya")
        .addAllObjects(bindException.getModel())
        .addObject("error", error)
        .addObject("combinacionsPropies", comb)
        .addObject("crearPenyaBB",bindingResult.getTarget());
	}

	public ModelAndView init(HttpServletRequest request,
			HttpServletResponse response){

		//Nova penya
		PenyaBackBean crearPenyaBB = new PenyaBackBean();
		UsuariRegistrat usuari = usuariRegistratDao.findByAlies(request.getParameter("usuari"));
		crearPenyaBB.setIdUsuari(usuari.getIdUsuari());
		crearPenyaBB.setNomUsuari(usuari.getAlies());
		crearPenyaBB.setEncuentroAnterior(Integer.valueOf(utilsDao.findById(ENFRONTAMENTS_ANTERIORS).getValor()));
		crearPenyaBB.setClassificacion(Integer.valueOf(utilsDao.findById(CLASSIFICACIO).getValor()));
		crearPenyaBB.setJugarLocal(Integer.valueOf(utilsDao.findById(LOCAL).getValor()));
		crearPenyaBB.setPrimeraVuelta(Integer.valueOf(utilsDao.findById(PRIMERA_VOLTA).getValor()));
		crearPenyaBB.setUltimosResultados(Integer.valueOf(utilsDao.findById(ULTIMS_RESULTATS).getValor()));
		
		//Combinacions propies.
		List<CombinacioPropia> comb = combinacioPropiaDao.findAll();
		ModelMap modelMap = new ModelMap();
		modelMap.addAttribute("crearPenyaBB", crearPenyaBB);
		modelMap.addAttribute("combinacionsPropies", comb);
		return new ModelAndView("usuari/crearPenya", modelMap);
	}

	public ModelAndView crearPenya (HttpServletRequest request,
			HttpServletResponse response, PenyaBackBean penyaBB){

		//Creem la penya.
		Penya penya = new Penya();
		penya.setNom(penyaBB.getNomPenya());
		penya.setDirectoriPenya(penyaBB.isDirectorioPenyas());
		penyaDao.store(penya);		

		//Creem el forum de la penya.
		Forum forum = new Forum();
		forum.setNom(penyaBB.getNomPenya());
		forum.setPenya(penya);
		forumDao.store(forum);

		//Convertir l'usuari en penyista.
		UsuariRegistrat usuari = usuariRegistratDao.findById(penyaBB.getIdUsuari());
		Penyista penyista = new Penyista();
		penyista.setUsuari(usuari);
		penyista.setAdministra(true);
		penyista.setPenya(penya);
		penyistaDao.store(penyista);

		//Assignar tots els equips de la penya a l'usuari, ja que de moment
		//no hi ha més usuaris i ha de poder fer una quiniela.
//		Set<EquipEnPenyista> equipsEnPenyista = assignarEquips(penyista);
//		penyista.setEquips(equipsEnPenyista);
//		penyistaDao.store(penyista);

		//Assignem els percentatges.
		Percentatge per1 = new Percentatge();
		per1.setPenya(penya);
		per1.setTipus(ENFRONTAMENTS_ANTERIORS);
		per1.setValor(String.valueOf(penyaBB.getEncuentroAnterior()));
		percentatgeDao.store(per1);
		
		Percentatge per2 = new Percentatge();
		per2.setPenya(penya);
		per2.setTipus(CLASSIFICACIO);
		per2.setValor(String.valueOf(penyaBB.getClassificacion()));
		percentatgeDao.store(per2);
		
		Percentatge per3 = new Percentatge();
		per3.setPenya(penya);
		per3.setTipus(LOCAL);
		per3.setValor(String.valueOf(penyaBB.getJugarLocal()));
		percentatgeDao.store(per3);
		
		Percentatge per4 = new Percentatge();
		per4.setPenya(penya);
		per4.setTipus(PRIMERA_VOLTA);
		per4.setValor(String.valueOf(penyaBB.getPrimeraVuelta()));
		percentatgeDao.store(per4);
		
		Percentatge per5 = new Percentatge();
		per5.setPenya(penya);
		per5.setTipus(ULTIMS_RESULTATS);
		per5.setValor(String.valueOf(penyaBB.getUltimosResultados()));
		percentatgeDao.store(per5);
		
		//Assignem les combinacions.
		//Propies
		Set<CombinacioPropia> combinacionsPropies = setCombinacionsPropies(penyaBB);
		//Generals
		Set<CombinacioGeneral> combinacionsGenerals = setCombinacionsGenerals(penyaBB);

		penya.setCombPropies(combinacionsPropies);
		penya.setCombGenerals(combinacionsGenerals);
		penyaDao.store(penya);

		//Enviar el mail amb la invitació a la penya.
		enviarMail(penyaBB);

		//Redirigir a la pàgina de MI PEÑA on és mostrarà el forum que s'haurà creat de nou.
		return new ModelAndView("redirect:/forum/init.htm?usuari=" + penyaBB.getNomUsuari());
	}

	private void enviarMail(PenyaBackBean penyaBB) {
		if(penyaBB.getEmail_1()!= null && !penyaBB.getEmail_1().equals("")){
			SimpleMailMessage msg = new SimpleMailMessage(this.mailMessage);
			msg.setTo(penyaBB.getEmail_1());
			msg.setText("Encara que costi de creure aquest mail s'ha enviat des de l'aplicació de " +
			"Gesfutbol mitjançat la meva conta de correu.");
			try{
				mailSender.send(msg);
			} catch(MailException ex) {
				throw new RuntimeException(ex);
			}
		}
	}

//	private Set<EquipEnPenyista> assignarEquips(Penyista penyista) {
//		List<Equip> equips = equipDao.findAll();
//		Set<EquipEnPenyista> equipsEnPenyista = new HashSet<EquipEnPenyista>();		
//		for(Equip e: equips){
//			IdEquipEnPenyista id = new IdEquipEnPenyista();
//			id.setEquip(e);
//			id.setPenyista(penyista);
//			EquipEnPenyista eep = new EquipEnPenyista();
//			eep.setId(id);
//			eep.setActiu(true);
//			equipEnPenyistaDao.store(eep);
//			equipsEnPenyista.add(eep);
//		}
//		return equipsEnPenyista;
//	}

	private Set<CombinacioPropia> setCombinacionsPropies(PenyaBackBean penyaBB) {
		Set<CombinacioPropia> combinacionsPropies = null;
		if(penyaBB.getCombPropia1()!= 0){
			combinacionsPropies = new HashSet<CombinacioPropia>();
			combinacionsPropies.add(combinacioPropiaDao.findById(penyaBB.getCombPropia1()));
		}
		if(penyaBB.getCombPropia2()!= 0){
			if(combinacionsPropies == null){
				combinacionsPropies = new HashSet<CombinacioPropia>();
			}
			combinacionsPropies.add(combinacioPropiaDao.findById(penyaBB.getCombPropia2()));
		}
		return combinacionsPropies;
	}

	private Set<CombinacioGeneral> setCombinacionsGenerals(PenyaBackBean penyaBB) {
		Set<CombinacioGeneral> combinacionsGenerals = null;
		if(penyaBB.getGeneralFix1()!= 0 
				|| penyaBB.getGeneralDob1()!= 0
				|| penyaBB.getGeneralTrip1()!= 0){
			combinacionsGenerals = new HashSet<CombinacioGeneral>();
			combinacionsGenerals.add(combinacioGeneralDao.storeIfExist(penyaBB.getGeneralFix1(),
					penyaBB.getGeneralDob1(),
					penyaBB.getGeneralTrip1()));
		}

		if(penyaBB.getGeneralFix2()!= 0 
				|| penyaBB.getGeneralDob2()!= 0
				|| penyaBB.getGeneralTrip2()!= 0){
			if(combinacionsGenerals == null){
				combinacionsGenerals = new HashSet<CombinacioGeneral>();
			}
			combinacionsGenerals.add(combinacioGeneralDao.storeIfExist(penyaBB.getGeneralFix2(),
					penyaBB.getGeneralDob2(),
					penyaBB.getGeneralTrip2()));
		}

		if(penyaBB.getGeneralFix3()!= 0 
				|| penyaBB.getGeneralDob3()!= 0
				|| penyaBB.getGeneralTrip3()!= 0){
			if(combinacionsGenerals == null){
				combinacionsGenerals = new HashSet<CombinacioGeneral>();
			}
			combinacionsGenerals.add(combinacioGeneralDao.storeIfExist(penyaBB.getGeneralFix3(),
					penyaBB.getGeneralDob3(),
					penyaBB.getGeneralTrip3()));
		}
		return combinacionsGenerals;
	}
}
